package core.proto;


import javax.swing.*;

import org.apache.commons.io.FilenameUtils;

import com.oreilly.servlet.HttpMessage;

import core.proto.rightwindow.InfovizRight;

import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Properties;
import java.util.Random;

import static app.constants.CollabVizConstants.*;
public class InfoViz extends JApplet implements KeyListener {
	/**
	 *
	 */
	static final String SEPARATOR = "SEPARATORFORSERVLET";

	private static URL codebase;

	private static final long serialVersionUID = 1L;
	public static String UserID;
	
	public static ButtonGroup buttonGroup;
	public static ButtonGroup sharingButtonGroup;
	
	public static boolean sharePostits;
	public static boolean postitSharingDiscretion;
	
	public static boolean splitCondition = false;
	
	public static boolean copyHilightCondition = true;
	
	private static final String SAVANT_USERNAME = "savant";
	private static final char[] SAVANT_PASSWORD = { 's', 'u', 'e', '_', 's', 'a', 'r', 'a', '_', 'n', 'i', 't', 'e', 's', 'h' };
	
	private boolean firstKey = true;
	
	public static int condition;

	//Old version
	//public static final int userToken = new Random().nextInt();
	//New version using MAC ADDRESS as uniuqe identifier, that way you can retrive your postits when logging in
	public static String userToken;
	
	public static InfoViz instance;
	
	private JPanel uploadPanel;
	
	private final JPanel loginPanel = new JPanel( new FlowLayout( FlowLayout.CENTER ) );
	
	private final JTextField username = new JTextField(8);
	private final JPasswordField password = new JPasswordField(8);
	private final JLabel feedback = new JLabel("Incorrect username/password", JLabel.LEFT);
	
	int contentPaneHeight;
	JTextField nick;
	JComboBox viewList;
	JCheckBox screenCapOption;
	JCheckBox hilightOption;

	GraphicsEnvironment ge;
    GraphicsDevice[] gs;
    GraphicsDevice left;
    public static GraphicsDevice right;
    
    static JFrame leftWindow;
    //not necessarily public
    public static InfovizRight rightWindow;
    
	public static URL codebase(){
		return codebase;
	}
	
	public static JFrame getLeft(){
		return leftWindow;
	}
	
	public static JFrame getRight() {
		return rightWindow;
	}
	
	public void init() {
		try {
			
			InetAddress ip;
			try {
				ip = InetAddress.getLocalHost();
		 
				NetworkInterface network = NetworkInterface.getByInetAddress(ip);
		 
				byte[] mac = network.getHardwareAddress();
		 
				StringBuilder sb = new StringBuilder();
				for (int i = 0; i < mac.length; i++) {
					sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));		
				}
				
		 
			} catch (UnknownHostException e) {
		 
				e.printStackTrace();
		 
			} catch (SocketException e){
		 
				e.printStackTrace();
		 
			}
			
			/**
			 * 
			 */
			
			
			ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
	        gs = ge.getScreenDevices();

	        left = gs[0];
	        right = gs.length > 1 ? gs[1] : gs[0];

			// Create directory at known location to store our data files. 
			new File(LOCAL_DIRECTORY).mkdir();
			// Folder for logs. 
			new File(LOG_FOLDER).mkdir();
			// Folder for highlights. 
			new File(NOTEPAD_HIGHLIGHT_FOLDER).mkdir();

			codebase = getCodeBase();

			// The HTML directory is also downloaded and unzipped since otherwise a lot of changes 
			// might be needed to the existing code base to make it work by loading directly from server.
			if (! new File(HTML_FILES_FOLDER).exists()){
				URL source = Util.getServerResource(FilenameUtils.concat(DATA_DIRECTORY, "HTML.zip"));
				String destFile =  FilenameUtils.concat(LOCAL_DIRECTORY, "HTML.zip");
				Util.copyFromUrlTo(source, destFile);
				Util.unzip(destFile);
			}
			if (! new File(HTML_FILES_FOLDER_ALEX).exists()){
				URL source = Util.getServerResource(FilenameUtils.concat(DATA_DIRECTORY, "HTML_Alex.zip"));
				String destFile =  FilenameUtils.concat(LOCAL_DIRECTORY, "HTML_Alex.zip");
				Util.copyFromUrlTo(source, destFile);
				Util.unzip(destFile);
			}
			if (! new File(HTML_FILES_FOLDER_PAT).exists()){
				URL source = Util.getServerResource(FilenameUtils.concat(DATA_DIRECTORY, "HTML_Pat.zip"));
				String destFile =  FilenameUtils.concat(LOCAL_DIRECTORY, "HTML_Pat.zip");
				Util.copyFromUrlTo(source, destFile);
				Util.unzip(destFile);
			}
			// Unfortunately the Lucene index has to be downloaded locally because it only works 
			if (! new File(INDEX_DIRECTORY).exists()){
				URL source = Util.getServerResource(FilenameUtils.concat(DATA_DIRECTORY, "index.zip"));
				String destFile =  FilenameUtils.concat(LOCAL_DIRECTORY, "index.zip");
				Util.copyFromUrlTo(source, destFile);
				Util.unzip(destFile);
			}
			SwingUtilities.invokeAndWait( new Runnable() {
				public void run() {
					UserID = "Default_User";
					uploadPanel = new JPanel( new FlowLayout( FlowLayout.CENTER ) );
					uploadPanel.setSize( WINDOW_WIDTH, WINDOW_HEIGHT);
					
					loginPanel.setSize( WINDOW_WIDTH, WINDOW_HEIGHT);
					
					username.setText("Username");
					password.setText("Password");
					
					password.addFocusListener(new FocusListener(){

						@Override
						public void focusGained(FocusEvent arg0) {
							char[] pass_check = { 'P', 'a', 's', 's', 'w', 'o', 'r', 'd'};
							if(Arrays.equals (password.getPassword(), pass_check)){
								password.setText("");
							}
						}

						@Override
						public void focusLost(FocusEvent arg0) {
						}
						
					});
					
					username.addKeyListener(new KeyListener(){

						@Override
						public void keyPressed(KeyEvent e) {
							if(firstKey){
								username.setText("");
								firstKey = false;
							}
							
							int key = e.getKeyCode();
						    if (key == KeyEvent.VK_ENTER) {
						    	if(username.getText().equals(SAVANT_USERNAME) && Arrays.equals (password.getPassword(), SAVANT_PASSWORD)){
									loginPanel.setVisible(false);
									setupUploadPanel();
									uploadPanel.setVisible(true);
									loginPanel.repaint();
									uploadPanel.repaint();
								}
								else{
									feedback.setVisible(true);
								}
						     }
						}

						@Override
						public void keyReleased(KeyEvent e) {
						}

						@Override
						public void keyTyped(KeyEvent e) {
						}
						
					});
					
					password.addKeyListener(new KeyListener(){

						@Override
						public void keyPressed(KeyEvent e) {
							int key = e.getKeyCode();
						    if (key == KeyEvent.VK_ENTER) {
						    	if(username.getText().equals(SAVANT_USERNAME) && Arrays.equals (password.getPassword(), SAVANT_PASSWORD)){
									loginPanel.setVisible(false);
									setupUploadPanel();
									uploadPanel.setVisible(true);
									loginPanel.repaint();
									uploadPanel.repaint();
								}
								else{
									feedback.setVisible(true);
								}
						     }
						}

						@Override
						public void keyReleased(KeyEvent e) {
						}

						@Override
						public void keyTyped(KeyEvent e) {
						}
						
					});
					
					JButton submit = new JButton("submit");
					submit.addActionListener(new ActionListener(){

						@Override
						public void actionPerformed(ActionEvent arg0) {
							if(username.getText().equals(SAVANT_USERNAME) && Arrays.equals (password.getPassword(), SAVANT_PASSWORD)){
								loginPanel.setVisible(false);
								setupUploadPanel();
								uploadPanel.setVisible(true);
								loginPanel.repaint();
								uploadPanel.repaint();
							}
							else{
								feedback.setVisible(true);
							}
						}
						
					});
					
					feedback.setVisible(false);
					
					loginPanel.add(username);
					loginPanel.add(password);
					loginPanel.add(submit);
					loginPanel.add(feedback);
					
					//SWITCH THESE FOR EASE
					//add(loginPanel);
					setupUploadPanel();
					
					setSize( WINDOW_WIDTH, WINDOW_HEIGHT );
					
				}
			} );
			
		} catch( Exception e ) {
			throw new Error(e);
		}
	}

	public void destroy() {
		uploadFile(getCodeBase());
	}
	
	public void setupUploadPanel(){
		nick = new JTextField(20);
		//uploadPanel.add(nick);
		
		 JPanel radioPanel = new JPanel(new GridLayout(1, 0));
		 JRadioButton alexButton = new JRadioButton("Alex");
		 JRadioButton patButton = new JRadioButton("Pat");
		 alexButton.setActionCommand("Alex");
		 patButton.setActionCommand("Pat");
	     buttonGroup = new ButtonGroup();
	     buttonGroup.add(alexButton);
	     buttonGroup.add(patButton);
	     buttonGroup.setSelected(alexButton.getModel(), true);
		 radioPanel.add(alexButton);
		 radioPanel.add(patButton);
		 uploadPanel.add(radioPanel);
		 
		//create the upload button but don't add it yet.
		final JButton startButton = new JButton( "Start" );
		startButton.addActionListener( new StartButtonHandler() );
		uploadPanel.add( startButton );

		String[] viewStrings = { "Complete View", "No Viz View", "No Notes View", "No Viz/Notes View" };

		//Create the combo box, select item at index 4.
		//Indices start at 0, so 4 specifies the pig.
		viewList = new JComboBox( viewStrings );
		viewList.setSelectedIndex( 0 );
		screenCapOption = new JCheckBox( "Enable Screen Capture" );
		uploadPanel.add( viewList );
		uploadPanel.add( screenCapOption );
		
		radioPanel = new JPanel(new GridLayout(0, 1));
		JRadioButton everythingButton = new JRadioButton("Condition 1");
		JRadioButton noneButton = new JRadioButton("Condition 2");
		JRadioButton someButton = new JRadioButton("Condition 3");
		JRadioButton halfShareButton = new JRadioButton("Condition 4");
		JRadioButton halfDontShareButton = new JRadioButton("Condition 5");
		everythingButton.setActionCommand("everything");
		noneButton.setActionCommand("none");
		someButton.setActionCommand("some");
		halfShareButton.setActionCommand("halfShare");
		halfDontShareButton.setActionCommand("halfDontShare");
		sharingButtonGroup = new ButtonGroup();
		sharingButtonGroup.add(everythingButton);
		sharingButtonGroup.add(noneButton);
		sharingButtonGroup.add(someButton);
		sharingButtonGroup.add(halfShareButton);
		sharingButtonGroup.add(halfDontShareButton);
		sharingButtonGroup.setSelected(everythingButton.getModel(), true);
		radioPanel.add(everythingButton);
		radioPanel.add(noneButton);
		radioPanel.add(someButton);
		uploadPanel.add(radioPanel);
		radioPanel = new JPanel(new GridLayout(0, 1));
		radioPanel.add(halfShareButton);
		radioPanel.add(halfDontShareButton);
		uploadPanel.add(radioPanel);
		
		hilightOption = new JCheckBox( "Copy Highlights" );
		hilightOption.setSelected(true);
		hilightOption.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				if(hilightOption.isSelected()){
					copyHilightCondition = true;
				}
				else{
					copyHilightCondition = false;
				}
			}
			
		});
		uploadPanel.add( hilightOption );
		
		add( uploadPanel );
	}

	public static void uploadFile(URL u) { 
		String logFolder = LOG_FOLDER;
		String date = Util.logDateFormat.format(Util.logFileCreationTime);
		String fileName1 = "syslog-"+"null"+"-"+date+".txt";
		String filePath1 = logFolder+"/"+fileName1;
		File f1 = new File(filePath1);
		StringBuffer s = new StringBuffer();
		s.append(fileName1+SEPARATOR);
		try {
			BufferedReader in = new BufferedReader(new FileReader(f1));
			String str;
			while ((str = in.readLine()) != null) {
				s.append(str);
			}
			in.close();
		} catch (IOException e) {
		}
		s.append(SEPARATOR);
		String fileName2 = "userlog-"+UserID+"-"+date+".txt";
		String filePath2 = logFolder+"/"+fileName2;
		File f2 = new File(filePath2);
		s.append(fileName2+SEPARATOR);
		try {
			BufferedReader in = new BufferedReader(new FileReader(f2));
			String str;
			while ((str = in.readLine()) != null) {
				s.append(str);
			}
			in.close();
		} catch (IOException e) {
		}
		try { 
			URL url = new URL(u, "/CollabVizUploader/uploader"); 
			HttpMessage msg = new HttpMessage(url); 
			Properties props = new Properties(); 
			props.put("message", s.toString()); 
			msg.sendPostMessage(props); 
		} catch (SocketException e) { 
			// Can't connect to host, report it and abandon the broadcast 
			System.out.println("Can't connect to host: " + e.getMessage()); 
		} catch (FileNotFoundException e) { 
			// Servlet doesn't exist, report it and abandon the broadcast 
			System.out.println("Resource not found: " + e.getMessage()); 
		} catch (Exception e) { 
			// Some other problem, report it and abandon the broadcast 
			//System.out.println("General exception: " + e.getClass().getName() + ": " + e.getMessage());
		}
	} 

	private void addRightWindow (String nick) {
        rightWindow = new InfovizRight(right.getDefaultConfiguration());
       int width = right.getDisplayMode().getWidth();
       int height = right.getDisplayMode().getWidth();
       
        
       //Switch these for single monitor
       rightWindow.setBounds(GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds().width, 0, width, height);
       //rightWindow.setBounds(0, 0, width, height);
       
       rightWindow.setVisible(true);

       setSize(0, 0);
	}
	
	private void addLeftWindow (int index, boolean isSelected) throws IOException {
		JFrame leftWindow = new JFrame(left.getDefaultConfiguration());
		Rectangle maxBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
		leftWindow.setBounds(0, 0, maxBounds.width, maxBounds.height);
		leftWindow.setVisible(true);
		leftWindow.setSize(maxBounds.width, maxBounds.height);
		Util.setAdjustedHeight(leftWindow.getContentPane().getHeight());
		AllComponents all =  new AllComponents(index, isSelected);
		leftWindow.getContentPane().add(all);
	}
	
	public static InfoViz getInstance(){
		return instance;
	}
	
	private class StartButtonHandler implements ActionListener {
		@Override
		public void actionPerformed( ActionEvent arg0 ) {
			final String prompt = "Please enter a nick name";
			try {
				//***GRAB NICKNAME 
				String txt = buttonGroup.getSelection().getActionCommand();
				
				if(sharingButtonGroup.getSelection().getActionCommand().equals("everything")){
					sharePostits = true;
					postitSharingDiscretion = false;
					condition = 1;
				}
				else if(sharingButtonGroup.getSelection().getActionCommand().equals("none")){
					sharePostits = false;
					postitSharingDiscretion = false;
					condition = 2;
				}
				else if(sharingButtonGroup.getSelection().getActionCommand().equals("some")){
					sharePostits = true;
					postitSharingDiscretion = true;
					condition = 3;
				}
				else if(sharingButtonGroup.getSelection().getActionCommand().equals("halfShare")){
					sharePostits = true;
					postitSharingDiscretion = false;
					splitCondition = true;
					condition = 4;
				}
				else if(sharingButtonGroup.getSelection().getActionCommand().equals("halfDontShare")){
					sharePostits = false;
					postitSharingDiscretion = false;
					splitCondition = true;
					condition = 5;
				}
				
				if(! txt.equals("") && ! txt.equals(prompt)) {
					UserID = txt;
					userToken = InfoViz.UserID;
					addLeftWindow(viewList.getSelectedIndex(), screenCapOption.isSelected());
					addRightWindow (txt);
					getContentPane().removeAll();
				} else {
					nick.setText(prompt);
				}

			} catch( IOException e ) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public void keyPressed(KeyEvent e) {
		int key = e.getKeyCode();
	    if (key == KeyEvent.VK_ENTER) {
	    	if(username.getText().equals(SAVANT_USERNAME) && password.getPassword().equals(SAVANT_PASSWORD)){
				loginPanel.setVisible(false);
				setupUploadPanel();
				uploadPanel.setVisible(true);
				loginPanel.repaint();
				uploadPanel.repaint();
			}
			else{
				feedback.setVisible(true);
			}
	     }
		
	}

	@Override
	public void keyReleased(KeyEvent e) {
	}

	@Override
	public void keyTyped(KeyEvent e) {	
	}
}
